#ifndef FILE_SYSTEM_H
#define FILE_SYSTEM_H

#include <string>
#include <map>
#include <sys/stat.h>
#include <fstream>
#include <mutex>
#include <memory>
#include <string>

namespace ftp
{
namespace Filesystem
{

enum class FileType
{
	Unknown,
	RegularFile,
	Dir,
	CharacterDevice,
	BlockDevice,
	Fifo,
	SymbolicLink,
	Socket,
};


/**
 * @brief Provide file status of specific path.
 *
 * Standard ftp list info:
 * -rw-------  1 peter         848 Dec 14 11:22 00README.txt
 *
 * "-rw-------" file type, owner user read/write/execute permission, group user read/write/execute permission,
 * other grou user read/write/execute permission
 *
 * "1" hard link number
 *
 * "peter" owner user name
 *
 * "848" file size(bytes)
 *
 * "Dec 14 11:22" file last modify time
 *
 * "00README.txt" file name
 *
 * @see
 * https://files.stairways.com/other/ftp-list-specs-info.txt
 */
class FileStatus
{
public:
	explicit FileStatus(const std::string& localPath);
	~FileStatus();

	// Check the file is exist.
	bool isOk() const;

	// Get the file type from stat()
	FileType type() const;

	// Check the file is a regular file
	bool isFile() const;
	// Check the file is a directory
	bool isDir() const;

	// Get the file size from stat()
	int64_t fileSize() const;

	bool permissionOwnerRead() const;
	bool permissionOwnerWrite() const;
	bool permissionOwnerExecute() const;
	bool permissionGroupRead() const;
	bool permissionGroupWrite() const;
	bool permissionGroupExecute() const;
	bool permissionOtherRead() const;
	bool permissionOtherWrite() const;
	bool permissionOtherExecute() const;

	// Get 9-bit permission string, just like "rwxrwxrwx"
	std::string permissionString() const;

	bool maskRealOwner() const;

	std::string ownerString() const;

	std::string groupString() const;

	std::string timeString() const;

	// Test if the file can be opened as a directory
	bool canOpenDir() const;

private:
	std::string getRealOwnerString() const;
	std::string getRealGroupString() const;

	bool maskRealOwner_;     // mask the real owner of the file?
	std::string path_;       // local path
	bool isOk_;

	struct stat fileStatus_{}; // file status by system call stat(2)

	static const char* kDefaultRealOwnerString;
	static const char* kDefaultRealGroupString;
};

/**
 * @brief Return brief file list of directory path
 *
 * @param localDirectoryPath: local directory path, require localDirectoryPath not end with '/'
 *
 * @return Map of every sub-file's (file name, file status) of directory specified by localDirectoryPath
 */
std::map<std::string, FileStatus> dirContent(const std::string& localDirectoryPath);

std::string simplifyPath(const std::string& path, char outputSeparator = '/');

std::string simplifyNativePath(const std::string& path);

} // namespace Filesystem
} // namespace ftp

#endif // !FILE_SYSTEM_H
